<?php
namespace pay;

class Qpay
{
    protected $url;
    protected $isSSL;
    protected $timeout;
    private $params;
    private $sign;

    /**
     * @param       $url       接口url
     * @param       $isSSL     是否使用证书发送请求
     * @param int   $timeout   超时
     */
    public function __construct($url, $isSSL, $timeout = 5){
        $this->url = $url;
        $this->isSSL = $isSSL;
        $this->timeout = $timeout;
    }

    public function getParams() {
        $post_data = file_get_contents("php://input");
        $params =  $this->xmlToArray($post_data);
        $this->params = $params;
        $this->sign = $params['sign'];
        return $params;
    }

    public function verifySign($key) {
        $sign = $this->getSign($this->params,$key);
        return $sign == $this->sign;
    }

    public function reqQpay($params,$id,$key){
        $ret = array();
        //商户号
        $params["mch_id"] = $id;
        //随机字符串
        $params["nonce_str"] = $this->createNoncestr();
        //签名
        $params["sign"] = $this->getSign($params,$key);
        //生成xml
        $xml = $this->arrayToXml($params);

        if(isset($this->isSSL)){
            $ret =  $this->reqByCurlSSLPost($xml, $this->url, $this->timeout);
        }else{
            $ret =  $this->reqByCurlNormalPost($xml, $this->url, $this->timeout);
        }
        return $ret;
    }




    /**
     * 生成随机串
     * @param int $length
     *
     * @return string
     */
    public function createNoncestr( $length = 32 ) {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ ){
            $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

    /**
     * 将参数转为hash形式
     * @param $params
     * @param $urlencode
     *
     * @return string
     */
    public function buildQueryStr($params) {
        $arrTmp = array();
        foreach ($params as $k => $v){
            //参数为空不参与签名
            if(isset($v) && $v != '' && $k != 'sign'){
                array_push($arrTmp, "$k=$v");
            }
        }
        return implode('&', $arrTmp);
    }

    /**
     * 获取参数签名
     * @param $params
     *
     * @return string
     */
    public function getSign($params,$key) {
        //第一步：对参数按照key=value的格式，并按照参数名ASCII字典序排序
        ksort($params);
        $stringA = $this->buildQueryStr($params);
        //第二步：拼接API密钥并md5
        $stringA = $stringA."&key=".$key;
        $stringA = md5($stringA);
        //转成大写
        $sign = strtoupper($stringA);
        return $sign;
    }

    /**
     * 数组转换成xml字符串
     * @param $arr
     * @return string
     */
    public function arrayToXml($arr) {
        $xml = "<xml>";
        foreach ($arr as $key => $val){
            if (is_numeric($val)){
                $xml.="<$key>$val</$key>";
            }
            else
                $xml.="<$key><![CDATA[$val]]></$key>";
        }
        $xml.="</xml>";
        return $xml;
    }

    /**
     * xml转换成数组
     * @param $xml
     * @return array|mixed|object
     */
    public function xmlToArray($xml) {
        $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $arr;
    }

    /**
     * 通用curl 请求接口。post方式
     * @param     $params
     * @param     $url
     * @param int $timeout
     *
     * @return bool|mixed
     */
    public function reqByCurlNormalPost($params, $url, $timeout = 10) {
        return $this->_reqByCurl($params, $url, $timeout, false);
    }

    /**
     * 使用ssl证书请求接口。post方式
     * @param     $params
     * @param     $url
     * @param int $timeout
     *
     * @return bool|mixed
     */
    public function reqByCurlSSLPost($params, $url, $timeout = 10) {
        return $this->_reqByCurl($params, $url, $timeout, true);
    }

    private static function _reqByCurl($params, $url, $timeout = 10, $needSSL = false) {
        $ch = curl_init();

        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_TIMEOUT, $timeout);

        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);

        curl_setopt($ch,CURLOPT_HEADER,FALSE);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
        //是否使用ssl证书
        if(isset($needSSL) && $needSSL != false){
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT, QPayConf_pub::SSLCERT_PATH);
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLKEY, QPayConf_pub::SSLKEY_PATH);
        }
        curl_setopt($ch,CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS, $params);
        $ret = curl_exec($ch);
        if($ret){
            curl_close($ch);
            //log($ret); //业务记录交互流水。注：流水日志影响性能，如请求量过大，请慎重设计日志。
            return $ret;
        }
        else {
            $error = curl_errno($ch);
            //log($error); //业务记录错误日志
            print_r($error);
            curl_close($ch);
            return false;
        }
    }
}
